<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>无人机路径规划</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }
        
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 10px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
            overflow: hidden;
        }
        
        .header {
            background: linear-gradient(45deg, #2c3e50, #34495e);
            color: white;
            padding: 20px;
            text-align: center;
        }
        
        .header h1 {
            font-size: 2.5em;
            margin-bottom: 10px;
        }
        
        .header p {
            font-size: 1.1em;
            opacity: 0.9;
        }
        
        .content {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 20px;
            padding: 20px;
        }
        
        .input-section, .output-section {
            background: #f8f9fa;
            border-radius: 8px;
            padding: 20px;
        }
        
        .section-title {
            font-size: 1.5em;
            color: #2c3e50;
            margin-bottom: 15px;
            border-bottom: 2px solid #3498db;
            padding-bottom: 5px;
        }
        
        .form-group {
            margin-bottom: 20px;
        }
        
        .form-group label {
            display: block;
            margin-bottom: 5px;
            font-weight: bold;
            color: #555;
        }
        
        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 15px;
        }
        
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        
        th {
            background-color: #3498db;
            color: white;
        }
        
        input[type="text"] {
            width: 100%;
            padding: 5px;
            border: 1px solid #ccc;
            border-radius: 3px;
        }
        
        .btn-add {
            background-color: #27ae60;
            color: white;
            border: none;
            padding: 8px 15px;
            border-radius: 5px;
            cursor: pointer;
            margin-right: 10px;
        }
        
        .btn-add:hover {
            background-color: #229954;
        }
        
        .btn-remove {
            background-color: #e74c3c;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 3px;
            cursor: pointer;
            font-size: 12px;
        }
        
        .btn-remove:hover {
            background-color: #c0392b;
        }
        
        .btn-plan {
            background: linear-gradient(45deg, #3498db, #2980b9);
            color: white;
            border: none;
            padding: 15px 30px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
            width: 100%;
            margin-top: 20px;
        }
        
        .btn-plan:hover {
            background: linear-gradient(45deg, #2980b9, #1f4e79);
        }
        
        .canvas-container {
            border: 2px solid #ddd;
            border-radius: 5px;
            margin-bottom: 15px;
            background: white;
        }
        
        #pathCanvas {
            display: block;
            width: 100%;
        }
        
        .result-info {
            background: #e8f5e8;
            padding: 15px;
            border-radius: 5px;
            border-left: 4px solid #27ae60;
            margin-bottom: 15px;
        }
        
        .error-info {
            background: #fdf2f2;
            padding: 15px;
            border-radius: 5px;
            border-left: 4px solid #e74c3c;
            margin-bottom: 15px;
        }
        
        .path-details {
            max-height: 200px;
            overflow-y: auto;
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 10px;
            background: white;
        }
        
        .loading {
            text-align: center;
            color: #666;
            font-style: italic;
        }
        
        @media (max-width: 768px) {
            .content {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🚁 无人机路径规划</h1>
            <p>基于欧拉路径的智能路径规划系统</p>
        </div>
        
        <div class="content">
            <!-- 输入区域 -->
            <div class="input-section">
                <h2 class="section-title">📍 参数设置</h2>
                
                <!-- 节点表格 -->
                <div class="form-group">
                    <label>节点列表</label>
                    <table id="nodesTable">
                        <thead>
                            <tr>
                                <th>节点ID</th>
                                <th>经度</th>
                                <th>纬度</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><input type="text" value="A" /></td>
                                <td><input type="text" value="117.001" /></td>
                                <td><input type="text" value="38.857" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                            <tr>
                                <td><input type="text" value="B" /></td>
                                <td><input type="text" value="117.010" /></td>
                                <td><input type="text" value="38.857" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                            <tr>
                                <td><input type="text" value="C" /></td>
                                <td><input type="text" value="117.005" /></td>
                                <td><input type="text" value="38.863" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                        </tbody>
                    </table>
                    <button class="btn-add" onclick="addNodeRow()">➕ 添加节点</button>
                </div>
                
                <!-- 边表格 -->
                <div class="form-group">
                    <label>边连接</label>
                    <table id="edgesTable">
                        <thead>
                            <tr>
                                <th>起始节点</th>
                                <th>目标节点</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td><input type="text" value="A" /></td>
                                <td><input type="text" value="B" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                            <tr>
                                <td><input type="text" value="B" /></td>
                                <td><input type="text" value="C" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                            <tr>
                                <td><input type="text" value="C" /></td>
                                <td><input type="text" value="A" /></td>
                                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
                            </tr>
                        </tbody>
                    </table>
                    <button class="btn-add" onclick="addEdgeRow()">➕ 添加边</button>
                </div>
                
                <!-- 起止点 -->
                <div class="form-group">
                    <label>起始节点</label>
                    <input type="text" id="startNode" value="A" placeholder="输入起始节点ID">
                </div>
                
                <div class="form-group">
                    <label>结束节点</label>
                    <input type="text" id="endNode" value="C" placeholder="输入结束节点ID">
                </div>
                
                <button class="btn-plan" onclick="planPath()">🚀 开始规划路径</button>
            </div>
            
            <!-- 输出区域 -->
            <div class="output-section">
                <h2 class="section-title">📊 规划结果</h2>
                
                <!-- 可视化画布 -->
                <div class="canvas-container">
                    <canvas id="pathCanvas" width="500" height="400"></canvas>
                </div>
                
                <!-- 结果信息 -->
                <div id="resultContainer">
                    <div class="loading">请设置参数并点击"开始规划路径"</div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 添加节点行
        function addNodeRow() {
            const table = document.getElementById('nodesTable').getElementsByTagName('tbody')[0];
            const row = table.insertRow();
            row.innerHTML = `
                <td><input type="text" value="" /></td>
                <td><input type="text" value="" /></td>
                <td><input type="text" value="" /></td>
                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
            `;
        }
        
        // 添加边行
        function addEdgeRow() {
            const table = document.getElementById('edgesTable').getElementsByTagName('tbody')[0];
            const row = table.insertRow();
            row.innerHTML = `
                <td><input type="text" value="" /></td>
                <td><input type="text" value="" /></td>
                <td><button class="btn-remove" onclick="removeRow(this)">删除</button></td>
            `;
        }
        
        // 删除行
        function removeRow(btn) {
            btn.closest('tr').remove();
        }
        
        // 收集表单数据
        function collectFormData() {
            // 收集节点数据
            const nodes = [];
            const nodeRows = document.querySelectorAll('#nodesTable tbody tr');
            for (let row of nodeRows) {
                const inputs = row.querySelectorAll('input');
                if (inputs[0].value && inputs[1].value && inputs[2].value) {
                    nodes.push({
                        id: inputs[0].value.trim(),
                        longitude: parseFloat(inputs[1].value),
                        latitude: parseFloat(inputs[2].value)
                    });
                }
            }
            
            // 收集边数据
            const edges = [];
            const edgeRows = document.querySelectorAll('#edgesTable tbody tr');
            for (let row of edgeRows) {
                const inputs = row.querySelectorAll('input');
                if (inputs[0].value && inputs[1].value) {
                    edges.push({
                        from_node: inputs[0].value.trim(),
                        to_node: inputs[1].value.trim()
                    });
                }
            }
            
            return {
                nodes: nodes,
                edges: edges,
                start_node: document.getElementById('startNode').value.trim(),
                end_node: document.getElementById('endNode').value.trim(),
                max_match_distance: 1000
            };
        }
        
        // 规划路径
        async function planPath() {
            const data = collectFormData();
            const resultContainer = document.getElementById('resultContainer');
            
            // 验证数据
            if (data.nodes.length < 2) {
                resultContainer.innerHTML = '<div class="error-info">❌ 至少需要2个节点</div>';
                return;
            }
            
            if (data.edges.length < 1) {
                resultContainer.innerHTML = '<div class="error-info">❌ 至少需要1条边</div>';
                return;
            }
            
            // 显示加载状态
            resultContainer.innerHTML = '<div class="loading">🔄 正在规划路径...</div>';
            
            try {
                const response = await fetch('/plan-path', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify(data)
                });
                
                const result = await response.json();
                
                if (result.success) {
                    displayResult(result, data.nodes);
                    drawPath(data.nodes, data.edges, result.path);
                } else {
                    resultContainer.innerHTML = `<div class="error-info">❌ ${result.message}</div>`;
                }
            } catch (error) {
                resultContainer.innerHTML = `<div class="error-info">❌ 请求失败: ${error.message}</div>`;
            }
        }
        
        // 显示结果
        function displayResult(result, nodes) {
            const pathStr = result.path.join(' → ');
            const details = result.path_details.map(detail => 
                `${detail.segment}. ${detail.from_node} → ${detail.to_node} [${detail.edge_type}] ${detail.distance}m`
            ).join('<br>');
            
            document.getElementById('resultContainer').innerHTML = `
                <div class="result-info">
                    <h3>✅ 路径规划成功</h3>
                    <p><strong>路径:</strong> ${pathStr}</p>
                    <p><strong>总距离:</strong> ${result.total_distance} 米</p>
                    <p><strong>节点数:</strong> ${nodes.length} 个</p>
                </div>
                <div class="path-details">
                    <strong>路径详情:</strong><br>
                    ${details}
                </div>
            `;
        }
        
        // 绘制路径图
        function drawPath(nodes, edges, path) {
            const canvas = document.getElementById('pathCanvas');
            const ctx = canvas.getContext('2d');
            
            // 清空画布
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            if (nodes.length === 0) return;
            
            // 计算坐标范围
            const lons = nodes.map(n => n.longitude);
            const lats = nodes.map(n => n.latitude);
            const minLon = Math.min(...lons);
            const maxLon = Math.max(...lons);
            const minLat = Math.min(...lats);
            const maxLat = Math.max(...lats);
            
            // 添加边距
            const lonRange = maxLon - minLon || 0.01;
            const latRange = maxLat - minLat || 0.01;
            const margin = 50;
            
            // 坐标转换函数
            function toCanvasX(lon) {
                return margin + (lon - minLon) / lonRange * (canvas.width - 2 * margin);
            }
            
            function toCanvasY(lat) {
                return canvas.height - margin - (lat - minLat) / latRange * (canvas.height - 2 * margin);
            }
            
            // 绘制网格
            ctx.strokeStyle = '#f0f0f0';
            ctx.lineWidth = 1;
            for (let i = 1; i <= 4; i++) {
                const x = i * canvas.width / 5;
                const y = i * canvas.height / 5;
                ctx.beginPath();
                ctx.moveTo(x, 0);
                ctx.lineTo(x, canvas.height);
                ctx.stroke();
                ctx.beginPath();
                ctx.moveTo(0, y);
                ctx.lineTo(canvas.width, y);
                ctx.stroke();
            }
            
            // 绘制所有边（灰色）
            ctx.strokeStyle = '#bdc3c7';
            ctx.lineWidth = 2;
            edges.forEach(edge => {
                const fromNode = nodes.find(n => n.id === edge.from_node);
                const toNode = nodes.find(n => n.id === edge.to_node);
                if (fromNode && toNode) {
                    ctx.beginPath();
                    ctx.moveTo(toCanvasX(fromNode.longitude), toCanvasY(fromNode.latitude));
                    ctx.lineTo(toCanvasX(toNode.longitude), toCanvasY(toNode.latitude));
                    ctx.stroke();
                }
            });
            
            // 绘制路径（蓝色，带箭头）
            if (path && path.length > 1) {
                ctx.strokeStyle = '#3498db';
                ctx.lineWidth = 4;
                
                for (let i = 0; i < path.length - 1; i++) {
                    const fromNode = nodes.find(n => n.id === path[i]);
                    const toNode = nodes.find(n => n.id === path[i + 1]);
                    
                    if (fromNode && toNode) {
                        const x1 = toCanvasX(fromNode.longitude);
                        const y1 = toCanvasY(fromNode.latitude);
                        const x2 = toCanvasX(toNode.longitude);
                        const y2 = toCanvasY(toNode.latitude);
                        
                        // 绘制线段
                        ctx.beginPath();
                        ctx.moveTo(x1, y1);
                        ctx.lineTo(x2, y2);
                        ctx.stroke();
                        
                        // 绘制箭头
                        const angle = Math.atan2(y2 - y1, x2 - x1);
                        const arrowLength = 15;
                        const arrowAngle = Math.PI / 6;
                        
                        ctx.beginPath();
                        ctx.moveTo(x2, y2);
                        ctx.lineTo(
                            x2 - arrowLength * Math.cos(angle - arrowAngle),
                            y2 - arrowLength * Math.sin(angle - arrowAngle)
                        );
                        ctx.moveTo(x2, y2);
                        ctx.lineTo(
                            x2 - arrowLength * Math.cos(angle + arrowAngle),
                            y2 - arrowLength * Math.sin(angle + arrowAngle)
                        );
                        ctx.stroke();
                    }
                }
            }
            
            // 绘制节点
            nodes.forEach((node, index) => {
                const x = toCanvasX(node.longitude);
                const y = toCanvasY(node.latitude);
                
                // 节点圆圈
                ctx.fillStyle = '#2c3e50';
                ctx.beginPath();
                ctx.arc(x, y, 8, 0, 2 * Math.PI);
                ctx.fill();
                
                // 节点标签
                ctx.fillStyle = '#2c3e50';
                ctx.font = '14px Arial';
                ctx.textAlign = 'center';
                ctx.fillText(node.id, x, y - 15);
                
                // 坐标标签
                ctx.fillStyle = '#7f8c8d';
                ctx.font = '10px Arial';
                ctx.fillText(`${node.longitude.toFixed(3)}, ${node.latitude.toFixed(3)}`, x, y + 25);
            });
            
            // 高亮起点和终点
            const startNode = nodes.find(n => n.id === document.getElementById('startNode').value.trim());
            const endNode = nodes.find(n => n.id === document.getElementById('endNode').value.trim());
            
            if (startNode) {
                const x = toCanvasX(startNode.longitude);
                const y = toCanvasY(startNode.latitude);
                ctx.fillStyle = '#27ae60';
                ctx.beginPath();
                ctx.arc(x, y, 12, 0, 2 * Math.PI);
                ctx.fill();
                ctx.fillStyle = 'white';
                ctx.font = 'bold 12px Arial';
                ctx.fillText('起', x, y + 4);
            }
            
            if (endNode) {
                const x = toCanvasX(endNode.longitude);
                const y = toCanvasY(endNode.latitude);
                ctx.fillStyle = '#e74c3c';
                ctx.beginPath();
                ctx.arc(x, y, 12, 0, 2 * Math.PI);
                ctx.fill();
                ctx.fillStyle = 'white';
                ctx.font = 'bold 12px Arial';
                ctx.fillText('终', x, y + 4);
            }
        }
        
        // 页面加载时绘制初始图
        window.onload = function() {
            drawPath(
                [
                    {id: 'A', longitude: 117.001, latitude: 38.857},
                    {id: 'B', longitude: 117.010, latitude: 38.857},
                    {id: 'C', longitude: 117.005, latitude: 38.863}
                ],
                [
                    {from_node: 'A', to_node: 'B'},
                    {from_node: 'B', to_node: 'C'},
                    {from_node: 'C', to_node: 'A'}
                ],
                []
            );
        };
    </script>
</body>
</html>
